<script>
  import formItem from './form-item'
  import { hasOwn, isDef } from '@web-utils/core'

  export default {
    name: 'FormItem',
    mixins: [formItem],
    inject: {
      formHolder: {
        default: {}
      },
      formItemConfig: {
        default: null
      }
    },
    computed: {
      gutter() {
        let parent = this.$parent
        while (parent && parent.$options.componentName !== 'ElRow') {
          parent = parent.$parent
        }
        return parent?.gutter ?? 0
      }
    },
    methods: {
      renderFormItem() {
        const {
          hideLabel,
          label,
          labelWidth,
          prop,
          rules,
          $scopedSlots,
          elFormItemProps,
          elForm,
          formHolder,
          formItemClass,
          required,
          block,
          half,
          wrapCol,
          wrapFormItem,
          disabled,
          formItemConfig,
          getRequireRule
        } = this
        let filterRules = rules
        let formRequired = required
        let rawRequired = required

        let formBlock = block
        let formWrapCol = wrapCol

        if (formItemConfig) {
          if (hasOwn(formItemConfig, 'block')) {
            formBlock = formItemConfig.block
          }
          if (hasOwn(formItemConfig, 'wrapCol')) {
            formWrapCol = formItemConfig.wrapCol
          }
        }

        const width = formBlock && half && formWrapCol ? `calc( 50% - ${this.gutter / 2}px)` : ''

        if (disabled || elForm?.disabled) {
          filterRules = []
          if (!formHolder.required && !formHolder.requiredFields?.includes(prop)) {
            rawRequired = false
          }
        } else {
          if (!formHolder.required && !formHolder.requiredFields?.includes(prop)) {
            formRequired = false
          }
          if (formRequired && !filterRules?.length && prop) {
            filterRules = [getRequireRule()]
          } else {
            if (!formRequired) {
              rawRequired = false
              if (filterRules) {
                filterRules = filterRules.filter(value => !value.required)
              }
            }
          }
        }

        const tips = $scopedSlots.tips?.()
        const hasTips = tips || this.tips
        const tipContent = hasTips ? (
          <ElTooltip effect="light" content={this.tips}>
            {tips ? <div slot="content">{tips}</div> : null}
            <i class="el-icon-info form-item-input-info"></i>
          </ElTooltip>
        ) : null

        return wrapFormItem ? (
          <ElFormItem
            style={{ width }}
            key={`${prop}-${formRequired}`}
            class={['form-item', formItemClass, { required: rawRequired, 'form-item-hide-label': hideLabel }]}
            scopedSlots={{
              ...$scopedSlots,
              default: hasTips
                ? () => (
                    <div class="form-item-input-wrapper">
                      {$scopedSlots.default?.()}
                      {tipContent}
                    </div>
                  )
                : $scopedSlots.default
            }}
            {...{ props: elFormItemProps }}
            label={label}
            ref="formItem"
            label-width={hideLabel ? '0' : labelWidth}
            prop={prop}
            rules={filterRules}
          />
        ) : hasTips ? (
          <div class="form-item-input-wrapper">
            {$scopedSlots.default?.()}
            {tipContent}
          </div>
        ) : (
          <div>{$scopedSlots.default?.()}</div>
        )
      },
      async clearValidate() {
        await this.$nextTick()
        this.$refs.formItem.clearValidate?.()
      },
      async validate() {
        await this.$nextTick()
        this.$refs.formItem.validate?.()
      }
    },
    render() {
      const { computeSpan, wrapCol, fixedSpan, formItemConfig, renderFormItem, elColProps, $scopedSlots, unwrap } = this

      let formWrapCol = wrapCol
      let reactive = false

      if (formItemConfig) {
        if (hasOwn(formItemConfig, 'wrapCol')) {
          formWrapCol = formItemConfig.wrapCol
        }
        if (hasOwn(formItemConfig, 'reactive')) {
          reactive = formItemConfig.reactive
        }
      }

      return unwrap ? (
        <div>{$scopedSlots.default?.()}</div>
      ) : formWrapCol ? (
        <ElCol
          {...{
            props: {
              ...elColProps,
              span: fixedSpan || computeSpan,
              ...(!isDef(fixedSpan) && reactive ? { xs: 24, sm: 12, md: 8, lg: 6, xl: 4 } : {})
            }
          }}>
          {renderFormItem()}
          {$scopedSlots?.below?.()}
        </ElCol>
      ) : (
        renderFormItem()
      )
    }
  }
</script>

<style lang="scss">
  .form-item.el-form-item {
    &.required {
      &:not(.is-no-asterisk) {
        .el-form-item__label {
          &::before {
            margin-right: 4px;
            color: #f56c6c;
            content: '*';
          }
        }
      }
    }

    .el-form-item__content {
      min-height: 29px;
    }

    &.el-form-item--mini {
      .el-form-item__content {
        line-height: 27px;
      }
    }

    &.form-item-hide-label {
      .el-form-item__label {
        display: none;
      }
    }
  }

  .form-item-input-wrapper {
    @include flex-row;
    align-items: center;

    > div,
    > form {
      width: 100%;
    }

    .el-input {
      @include flex-item;
    }

    .form-item-input-info {
      margin-left: 4px;
      color: #808080;
      font-size: 16px;
      cursor: help;
    }
  }
</style>
